﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraBars;
using ZCrawler;
using NCrawler.Extensions;

namespace ZCrawlerManager
{
    public partial class FrmRuleSetting : DevExpress.XtraEditors.XtraForm
    {
        public DialogResult result;
        public ZBasicRule rule;
        private List<ZCrawlDataProcessor> processors;
        private List<ZFilter> filters;
        private string baseUrl;
        public FrmRuleSetting(string[] fields, string b_url)
        {
            InitializeComponent();
            baseUrl = b_url;
            processors = new List<ZCrawlDataProcessor>();
            filters = new List<ZFilter>();
            cmbParseType.Properties.Items.AddRange(Enum.GetNames(typeof(ZXPathType)));
            cmbParseType.SelectedIndex = 0;
            foreach (string field in fields)
            {
                BarButtonItem item = new BarButtonItem(barManager1, field);
                item.ItemClick += item_ItemClick;
                drpMenu.AddItem(item);
            }
            chkEnableFilter.Checked = true;
            chkEnableFilter.Checked = false;
            cmbFilter.Properties.Items.AddRange(Enum.GetNames(typeof(ZFilterType)));
            result = System.Windows.Forms.DialogResult.Cancel;
        }
        public FrmRuleSetting(ZBasicRule r,string[] fields,string b_url)
        {
            InitializeComponent();
            baseUrl = b_url;
            cmbParseType.Properties.Items.AddRange(Enum.GetNames(typeof(ZXPathType)));
            result = System.Windows.Forms.DialogResult.Cancel;
            rule = r;
            processors = rule.processors;
            filters = rule.filters;
            txtField.Text = rule.FieldName;
            txtBegin.Text = rule.startTag;
            txtEnd.Text = rule.endTag;
            txtMark.Text = rule.navMark;
            txtXPath.Text = rule.XPathes.IsNull() || rule.XPathes.Count == 0 ? "" : rule.XPathes.First();
            txtTree.Text = rule.searchFieldTree;
            lstParseProcessor.Items.AddRange(processors.Select(p => p.Description).ToArray());
            
            cmbParseType.SelectedItem = Enum.GetName(typeof(ZXPathType), rule.type);
            if(rule.GetType().IsEquivalentTo(typeof(ZRuleNav)))
            {
                tabRule.SelectedTabPageIndex = 0;
            }
            else if(rule.GetType().IsEquivalentTo(typeof(ZRuleXPath)))
            {
                tabRule.SelectedTabPageIndex = 1;
            }
            else if (rule.GetType().IsEquivalentTo(typeof(ZRuleRange)))
            {
                tabRule.SelectedTabPageIndex = 2;
            }
            else if (rule.GetType().IsEquivalentTo(typeof(ZRuleDerived)))
            {
                foreach (string field in fields)
                {
                    BarButtonItem item = new BarButtonItem(barManager1, field);
                    item.ItemClick += item_ItemClick;
                    drpMenu.AddItem(item);
                }
                txtDerivedRule.Text = ((ZRuleDerived)rule).DerivedString;
                tabRule.SelectedTabPageIndex = 3;
            }
            else if(rule.GetType().IsEquivalentTo(typeof(ZRuleJson)))
            {
                tabRule.SelectedTabPageIndex = 4;
            }

            chkEnableFilter.Checked = true;
            chkEnableFilter.Checked = rule.EnableFilters;
            if(filters.Count > 0)
            {
                lstFilter.Items.AddRange(filters.Select(f => f.FilterRule).ToArray());
            }
            cmbFilter.Properties.Items.AddRange(Enum.GetNames(typeof(ZFilterType)));
            result = System.Windows.Forms.DialogResult.Cancel;
        }

        void item_ItemClick(object sender, ItemClickEventArgs e)
        {
            string appendString = "";
            if(txtDerivedRule.Text.IsNullOrEmpty())
                appendString = "#FAppend#{0}".FormatWith(e.Item.Caption);
            else appendString = "+#FAppend#{0}".FormatWith(e.Item.Caption);
            int s_idx = txtDerivedRule.SelectionStart;
            txtDerivedRule.Text = txtDerivedRule.Text.Insert(s_idx, appendString);
            txtDerivedRule.SelectionStart = s_idx + appendString.Length;
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            if(txtField.Text.IsNullOrEmpty())
            {
                XtraMessageBox.Show("Null Field Detect.");
                return;
            }
            int tabIndex = tabRule.SelectedTabPageIndex;
            switch(tabIndex)
            {
                case 0:
                    if (txtMark.Text.IsNullOrEmpty())
                    {
                        XtraMessageBox.Show("Null Mark Detect.");
                        return;
                    }
                    rule = new ZRuleNav(txtField.Text)
                    {
                        navMark = txtMark.Text
                    };
                    break;
                case 1:
                    if (txtXPath.Text.IsNullOrEmpty())
                    {
                        XtraMessageBox.Show("Null XPath Detect.");
                        return;
                    }
                    //Remove tbody tag
                    rule = new ZRuleXPath((ZXPathType)Enum.Parse(typeof(ZXPathType), cmbParseType.SelectedItem.ToString()), txtField.Text);
                    ((ZRuleXPath)rule).AddXPath(txtXPath.Text.Replace("/tbody",""));
                    break;
                case 2:
                    if (txtBegin.Text.IsNullOrEmpty() || txtEnd.Text.IsNullOrEmpty())
                    {
                        XtraMessageBox.Show("Input range first.");
                        return;
                    }
                    rule = new ZRuleRange(txtBegin.Text, txtEnd.Text, txtField.Text);
                    break;
                case 3:
                    if (txtDerivedRule.Text.IsNullOrEmpty())
                    {
                        XtraMessageBox.Show("No rule defined");
                        return;
                    }
                    rule = new ZRuleDerived(txtField.Text) { DerivedString = txtDerivedRule.Text };
                    break;
                case 4:
                    if(txtTree.Text.IsNullOrEmpty())
                    {
                        XtraMessageBox.Show("No rule defined");
                        return;
                    }
                    rule = new ZRuleJson(txtField.Text) { searchFieldTree = txtTree.Text };
                    break;
            }
            rule.processors = processors;
            if (chkEnableFilter.Checked)
            {
                rule.EnableFilters = true;
                rule.filters = filters;
            }
            else
            {
                rule.EnableFilters = false;
            }
            result = System.Windows.Forms.DialogResult.OK;
            this.Close();
        }

        private void btnAddParseProcessor_Click(object sender, EventArgs e)
        {
            using(FrmCrawlProcess frm = new FrmCrawlProcess(null,baseUrl))
            {
                frm.ShowDialog();
                if(frm.result == System.Windows.Forms.DialogResult.OK)
                {
                    ZCrawlDataProcessor p = frm.processor;
                    processors.Add(p);
                    lstParseProcessor.Items.Add(p.Description);
                }
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            result = System.Windows.Forms.DialogResult.Cancel;
            this.Close();
        }

        private void simpleButton2_Click(object sender, EventArgs e)
        {
            int index = lstParseProcessor.SelectedIndex;
            if (index == -1) return;
            processors.RemoveAt(index);
            lstParseProcessor.Items.RemoveAt(index);
        }

        private void chkEnableFilter_CheckedChanged(object sender, EventArgs e)
        {
            txtFilter.Enabled = cmbFilter.Enabled = lstFilter.Enabled = btnAddFilter.Enabled = btnDeleteFilter.Enabled = chkEnableFilter.Checked;
        }

        private void lstFilter_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void btnAddFilter_Click(object sender, EventArgs e)
        {
            ZFilterType f_type = (ZFilterType)Enum.Parse(typeof(ZFilterType), cmbFilter.SelectedItem.ToString());
            switch(f_type)
            {
                case ZFilterType.StringFilter:
                    ZStringMatchFilter filter = new ZStringMatchFilter(){FilterRule = txtFilter.Text};
                    lstFilter.Items.Add(filter.FilterRule);
                    filters.Add(filter);
                    break;
            }
        }

        private void btnDeleteFilter_Click(object sender, EventArgs e)
        {
            int index = lstFilter.SelectedIndex;
            if (index == -1) return;
            filters.RemoveAt(index);
            lstFilter.Items.RemoveAt(index);
        }
    }
}